package com.jrh.biz.member;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.jrh.common.encrypt.CreateMD5;
import com.jrh.dal.UserDao;
import com.jrh.domain.entity.User;

/**
 * oauth2外站登录服务
 * 
 * @author jasen.hsu.cn@gmail.com 2012-7-19 上午11:25:34
 */
public class Oauth2ServiceImpl implements Oauth2Service {

    private static final Logger logger            = LoggerFactory.getLogger(Oauth2ServiceImpl.class);

    private UserDao             userDao;

    private String              taobaoAppSecret   = "28dbdd21127f438a59db0cb9f8f620f6";

    private String              taobaoAppkey      = "488703";

    private String              taobaoCallbackUrl = "http://www.jiaruhe.com/connect/taobao.htm";

    private String              qqAppSecret       = "28dbdd21127f438a59db0cb9f8f620f6";

    private String              qqAppkey          = "488703";

    private String              qqCallbackUrl     = "http://www.jiaruhe.com/connect/callback/qq.htm";

    private String              weiboAppSecret    = "28dbdd21127f438a59db0cb9f8f620f6";

    private String              weiboAppkey       = "488703";

    private String              weiboCallbackUrl  = "http://www.jiaruhe.com/connect/callback/weibo.htm";

    /*
     * (non-Javadoc)
     * @see com.jrh.biz.member.Oauth2Service#getTaobaoUser(java.lang.String, java.lang.String)
     */
    @Override
    public User getTaobaoUser(String topParams, String topSign) {
        boolean success = false;
        User user = null;
        Map<String, String> taobaoUser = null;
        try {
            success = verifyTopResponse(topParams, topSign, taobaoAppSecret);
            taobaoUser = convertBase64StringtoMap(topParams);
        } catch (Exception e) {
            logger.error("login from taobao error topParams: " + topParams);
            logger.error("login from taobao error topSign: " + topSign);
            logger.error("login from taobao error", e);
        }
        if (!success || taobaoUser == null) {
            return null;
        }
        // {ts=1337825443676, nick=中文测试nick}
        String taobaoNickname = taobaoUser.get("nick");
        if (StringUtils.isBlank(taobaoNickname)) {
            return user;
        }
        user = userDao.getUserByLoginIdAndSite(taobaoNickname, User.JRH_TAOBAO_USER_SITE);
        /** 本地用户不存在,新建用户 */
        if (user == null) {
            try {
                user = new User();
                user.setLoginId(taobaoNickname);
                user.setNickname("tb_" + taobaoNickname + "_" + ((int) (Math.random() * 1000)));
                user.setPassword(CreateMD5.createMD5("jrh"));
                user.setSite(User.JRH_TAOBAO_USER_SITE);
                user.setGmtModified(new Date());
                user.setUserType(User.USER_TYPE_BUYER);
                userDao.create(user);
            } catch (Exception e) {
                logger.error("create taobao user 2 jrh error:", e);
            }
            user = userDao.getUserByLoginIdAndSite(taobaoNickname, User.JRH_TAOBAO_USER_SITE);
        }
        return user;
    }

    public User getQqUser(String body, String openId) {
        User user = null;
        if (StringUtils.isBlank(body) || StringUtils.isBlank(openId) || !body.contains("\"ret\":0")) {
            return null;
        }
        user = userDao.getUserByLoginIdAndSite(openId, User.JRH_QQ_USER_SITE);
        /** 本地用户不存在,新建用户 */
        if (user == null) {
            try {
                user = new User();
                user.setLoginId(openId);
                user.setNickname("qq_" + ((int) (Math.random() * 10000000)) + "_" + ((int) (Math.random() * 1000)));
                user.setPassword(CreateMD5.createMD5("jrh"));
                user.setSite(User.JRH_QQ_USER_SITE);
                user.setGmtModified(new Date());
                user.setUserType(User.USER_TYPE_BUYER);
                userDao.create(user);
            } catch (Exception e) {
                logger.error("create qq user 2 jrh error:", e);
            }
            user = userDao.getUserByLoginIdAndSite(openId, User.JRH_QQ_USER_SITE);
        }
        return user;
    }

    @Override
    public User getWeiboUser(String body, String openId) {
        // TODO Auto-generated method stub
        return null;
    }

    public static void main(String[] args) throws Exception {
        String topParams = URLDecoder.decode("bmljaz3kuK3mlofmtYvor5VuaWNrJnRzPTEzMzc4MjU0NDM2NzY%3D", "UTF-8");
        String topSign = URLDecoder.decode("kxQT%2F6j7eblJLORflcz9qw%3D%3D", "UTF-8");
        String appSecret = "28dbdd21127f438a59db0cb9f8f620f6";
        // 先校验签名
        boolean success = verifyTopResponse(topParams, topSign, appSecret);
        if (success) {
            // 再解析参数
            System.out.println(convertBase64StringtoMap(topParams));
            // TODO 实际使用时建议再校验时间戳，比如时间误差5分钟内视为有效
        }
    }

    /**
     * 验证TOP回调地址的签名是否合法。要求所有参数均为已URL反编码的。
     * 
     * @param topParams TOP私有参数（未经BASE64解密）
     * @param topSign TOP回调签名
     * @param appSecret 应用密钥
     * @return 验证成功返回true，否则返回false
     * @throws NoSuchAlgorithmException
     * @throws IOException
     */
    private static boolean verifyTopResponse(String topParams, String topSign, String appSecret)
                                                                                                throws NoSuchAlgorithmException,
                                                                                                IOException {
        StringBuilder result = new StringBuilder();
        MessageDigest md5 = MessageDigest.getInstance("MD5");
        result.append(topParams).append(appSecret);
        byte[] bytes = md5.digest(result.toString().getBytes("UTF-8"));
        sun.misc.BASE64Encoder encoder = new sun.misc.BASE64Encoder();
        return encoder.encode(bytes).equals(topSign);
    }

    /**
     * 把经过BASE64编码的字符串转换为Map对象
     * 
     * @param str
     * @return
     * @throws Exception
     */
    private static Map<String, String> convertBase64StringtoMap(String str) {
        if (str == null) return null;
        String keyvalues = null;
        try {
            keyvalues = new String(Base64.decodeBase64(URLDecoder.decode(str, "UTF-8").getBytes("UTF-8")));
        } catch (UnsupportedEncodingException e) {
            logger.error("taobao user convertBase64StringtoMap error:", e);
        }
        String[] keyvalueArray = keyvalues.split("\\&");
        Map<String, String> map = new HashMap<String, String>();
        for (String keyvalue : keyvalueArray) {
            String[] s = keyvalue.split("\\=");
            if (s == null || s.length != 2) return null;
            map.put(s[0], s[1]);
        }
        return map;
    }

    public String getTaobaoAppkey() {
        return taobaoAppkey;
    }

    public void setTaobaoAppkey(String taobaoAppkey) {
        this.taobaoAppkey = taobaoAppkey;
    }

    public void setTaobaoAppSecret(String taobaoAppSecret) {
        this.taobaoAppSecret = taobaoAppSecret;
    }

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    public String getTaobaoCallbackUrl() {
        return taobaoCallbackUrl;
    }

    public void setTaobaoCallbackUrl(String taobaoCallbackUrl) {
        this.taobaoCallbackUrl = taobaoCallbackUrl;
    }

    public String getQqAppSecret() {
        return qqAppSecret;
    }

    public void setQqAppSecret(String qqAppSecret) {
        this.qqAppSecret = qqAppSecret;
    }

    public String getQqAppkey() {
        return qqAppkey;
    }

    public void setQqAppkey(String qqAppkey) {
        this.qqAppkey = qqAppkey;
    }

    public String getQqCallbackUrl() {
        return qqCallbackUrl;
    }

    public void setQqCallbackUrl(String qqCallbackUrl) {
        this.qqCallbackUrl = qqCallbackUrl;
    }

    public UserDao getUserDao() {
        return userDao;
    }

    public String getTaobaoAppSecret() {
        return taobaoAppSecret;
    }

    public String getWeiboAppSecret() {
        return weiboAppSecret;
    }

    public void setWeiboAppSecret(String weiboAppSecret) {
        this.weiboAppSecret = weiboAppSecret;
    }

    public String getWeiboAppkey() {
        return weiboAppkey;
    }

    public void setWeiboAppkey(String weiboAppkey) {
        this.weiboAppkey = weiboAppkey;
    }

    public String getWeiboCallbackUrl() {
        return weiboCallbackUrl;
    }

    public void setWeiboCallbackUrl(String weiboCallbackUrl) {
        this.weiboCallbackUrl = weiboCallbackUrl;
    }

}
